Apple, the Apple logo, and Macintosh are registered trademarks of Apple Computer, Inc.
Mac and OpenDoc are trademarks of Apple Computer, Inc.
OpenDoc b1c1 includes a change to the implementation of the Layout and Imaging subsystems that has a large effect on how part editor code must handle shape and transform objects. This document describes the change, and how to modify dependent code in part editors to work in a post-b1c1 world.
The change:
Classes ODShape and ODTransform are now derived from ODRefCntObject. This means shape and transform objects are now reference counted. Previously these objects were explicitly deleted, but now that they are reference counted, that is no longer possible.
There are a large number of calls in classes ODFacet and ODFrame that have shapes or transforms as either parameters or return values. The usage model for all of these calls has been changed. It’s easy to know which calls have changed – the calls in question all have a “biasCanvas” parameter – but basically any ODFacet or ODFrame call that involves a shape or transform has changed.
Modifying dependent code:
– Getters
• Most importantly, do not delete any geometry object returned from a frame or facet.
• Any call that returns geometry must be balanced by a subsequent Release() call on that object. For example:
This applies to shapes and transforms which have just been created by factory methods as well. That is, newly created objects are born with a reference count of 1.
• Unfortunately, geometry can’t be used as conveniently in a functional fashion. Wheras before you could say:
• When you pass a shape or transform into a call, it is assumed the refcount of the object is at least one. You must give up ownership of the object to the frame or facet, so after you call the setter, you should release your reference to the object.
newShape = facet->CreateShape(ev);
// fill in shape data...
facet->ChangeClipShape(ev, newShape, biasCanvas);
newShape->Release(ev);
newShape = kODNULL;
The facet (or frame) will increment the geometry object’s refcount to keep it around. But make sure you don’t Release the object until after calling the setter, or the layout object won’t have a chance to increment its refcount before it drops to zero.
– Modifying geometry efficiently
• There are a number of calls on ODFrame and ODFacet that let you change the value of a shape or transform. Previously this necessitated a lot of copying. Now this can be accomplished more efficiently. Before you had to do
This allows you to modify and re-use the same object without copying. It’s probably a good idea not to hang onto the modified shape, but rather get it again next time you want to use it. That way the memory can be reclaimed if the facet/frame goes away. More importantly, if the object changes for some reason, and you were modifying the object, not creating its value from scratch, you could end up with incorrect results. And it’s not that much overhead to get the object again later.
– Making copies
There is a utility function, ODCopyAndRelease, which can make copying of geometry both more convenient and more efficient. (You'll find it in the ODUtils utility.) Here’s how you copy a shape:
ODCopyAndRelease will copy the frameShape, and release it. For extra efficiency, if the refcount of the shape is exactly one, it will just return the shape itself (which is equivalent to copying and releasing it). There is an equivalent ODCopyAndRelease for Transforms as well.
– Automating release calls
A new C++ utility called TempObj can make it much simpler to keep track of objects that need to be released. It even ensures that the objects get released if an exception is thrown. For details, read the “Temporary Objects and References” document in the Tech Notes folder.